package org.xp.judgeplatform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.AllArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import org.xp.judgeplatform.config.FileUploadConfig;
import org.xp.judgeplatform.converter.UserConverter;
import org.xp.judgeplatform.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.xp.judgeplatform.mapper.UserMapper;
import org.springframework.stereotype.Service;
import org.xp.judgeplatform.pojo.dto.UserDTO.*;
import org.xp.judgeplatform.pojo.entity.User;
import org.xp.judgeplatform.pojo.vo.UserVO.UserVO;
import org.xp.judgeplatform.service.UserService;
import org.xp.judgeplatform.util.FileUploadUtil;
import org.xp.judgeplatform.util.JwtUtil;
import org.xp.judgeplatform.util.PasswordUtil;

@Service
@Slf4j
@AllArgsConstructor
public class UserServiceImpl implements UserService {

    private final UserMapper userMapper;
    private final UserConverter userConverter;
    private final FileUploadUtil fileUploadUtil;
    private final FileUploadConfig fileUploadConfig;
    private final PasswordUtil passwordUtil;
    private final JwtUtil jwtUtil;

    @Override
    public UserVO login(UserLoginDTO userLoginDTO) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", userLoginDTO.getUsername());

        User user = userMapper.selectOne(queryWrapper);

        if (user == null) {
            log.warn("登录失败，用户'{}'不存在", userLoginDTO.getUsername());
            throw new BusinessException(400, "用户名或密码错误");
        }

        if (!passwordUtil.matches(userLoginDTO.getPassword(), user.getPassword())) {
            log.warn("登录失败，用户'{}'密码错误", userLoginDTO.getUsername());
            throw new BusinessException(400, "用户名或密码错误");
        }

        log.info("用户 '{}' 登录成功", user.getUsername());
        return getUserVO(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVO register(UserRegisterDTO userRegisterDTO) {
        try {
            log.info("开始注册用户：{}", userRegisterDTO.getUsername());

            // 验证用户名唯一性
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("username", userRegisterDTO.getUsername());
            User existingUser = userMapper.selectOne(queryWrapper);

            if (existingUser != null) {
                throw new BusinessException(400, "用户名已存在");
            }

            // 验证邮箱唯一性
            if (userRegisterDTO.getEmail() != null && !userRegisterDTO.getEmail().trim().isEmpty()) {
                QueryWrapper<User> emailQuery = new QueryWrapper<>();
                emailQuery.eq("email", userRegisterDTO.getEmail().trim());
                User existingEmailUser = userMapper.selectOne(emailQuery);

                if (existingEmailUser != null) {
                    throw new BusinessException(400, "邮箱已被注册");
                }
            }

            // 创建新用户
            User newUser = new User();
            newUser.setUsername(userRegisterDTO.getUsername());
            newUser.setPassword(passwordUtil.encodePassword(userRegisterDTO.getPassword()));
            newUser.setEmail(userRegisterDTO.getEmail());
            newUser.setRole(User.ROLE_USER);
            newUser.setStatus(User.STATUS_NORMAL);

            int result = userMapper.insert(newUser);
            if (result == 0) {
                throw new BusinessException(500, "注册失败");
            }

            log.info("用户注册成功：{}", newUser.getUsername());
            return getUserVO(newUser);

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("注册失败，用户名: {}", userRegisterDTO.getUsername(), e);
            throw new BusinessException(500, "注册失败：" + e.getMessage());
        }
    }

    @NotNull
    private UserVO getUserVO(User user) {
        UserVO userVO = userConverter.toUserVO(user);
        UserDetails userDetails = new org.xp.judgeplatform.security.UserPrincipal(user);

        String token = jwtUtil.generateToken(userDetails);
        String refreshToken = jwtUtil.generateRefreshToken(userDetails);
        userVO.setToken(token);
        userVO.setRefreshToken(refreshToken);

        return userVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVO updateUserInfo(Integer userId, UserProfileDTO userProfileDTO) {
        log.info("开始更新用户信息，用户ID: {}", userId);

        User existingUser = userMapper.selectById(userId);
        if (existingUser == null) {
            log.warn("更新失败，用户ID {} 不存在", userId);
            throw new BusinessException(404, "用户不存在");
        }

        // 检查邮箱是否被其他用户使用
        if (userProfileDTO.getEmail() != null && !userProfileDTO.getEmail().trim().isEmpty()) {
            String newEmail = userProfileDTO.getEmail().trim();
            if (!newEmail.equals(existingUser.getEmail())) {
                QueryWrapper<User> emailQuery = new QueryWrapper<>();
                emailQuery.eq("email", newEmail);
                emailQuery.ne("id", userId);
                User existingEmailUser = userMapper.selectOne(emailQuery);

                if (existingEmailUser != null) {
                    throw new BusinessException(400, "该邮箱已被其他用户使用");
                }
            }
        }

        // 更新用户信息
        User updateUser = new User();
        updateUser.setId(userId);

        if (userProfileDTO.getEmail() != null && !userProfileDTO.getEmail().trim().isEmpty()) {
            updateUser.setEmail(userProfileDTO.getEmail().trim());
        }
        if (userProfileDTO.getPhone() != null && !userProfileDTO.getPhone().trim().isEmpty()) {
            updateUser.setPhone(userProfileDTO.getPhone().trim());
        }
        if (userProfileDTO.getIntro() != null) {
            updateUser.setIntro(userProfileDTO.getIntro().trim());
        }

        int updateCount = userMapper.updateById(updateUser);
        if (updateCount == 0) {
            throw new BusinessException(500, "更新用户信息失败");
        }

        User updatedUser = userMapper.selectById(userId);
        UserVO userVO = userConverter.toUserVO(updatedUser);

        log.info("用户信息更新成功，用户ID: {}", userId);
        return userVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateAvatar(Integer userId, MultipartFile avatar) {
        log.info("开始更新用户头像，用户ID: {}", userId);

        try {
            User existingUser = userMapper.selectById(userId);
            if (existingUser == null) {
                throw new BusinessException(404, "用户不存在");
            }

            // 验证文件格式和大小
            fileUploadUtil.validateImageFile(avatar);

            // 保存旧头像路径（用于后续删除）
            String oldAvatarPath = existingUser.getAvatar();

            // 上传新头像
            String avatarUrl = fileUploadUtil.uploadAvatar(avatar);

            // 更新数据库中的头像路径
            User updateUser = new User();
            updateUser.setId(userId);
            updateUser.setAvatar(avatarUrl);
            int updateCount = userMapper.updateById(updateUser);

            if (updateCount == 0) {
                throw new BusinessException(500, "更新头像记录失败");
            }

            // 删除旧头像文件（如果存在）
            if (oldAvatarPath != null && !oldAvatarPath.isEmpty()) {
                fileUploadUtil.deleteOldAvatar(oldAvatarPath);
            }
            
            log.info("用户 {} 头像更新成功，新头像: {}", userId, avatarUrl);
            return fileUploadConfig.getAccess().getBaseUrl() + avatarUrl;

        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("更新头像时发生异常，用户ID: {}", userId, e);
            throw new BusinessException(500, "更新头像失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changePassword(Integer userId, UserPasswordDTO userPasswordDTO) {
        log.info("开始修改用户密码，用户ID: {}", userId);

        User existingUser = userMapper.selectById(userId);
        if (existingUser == null) {
            log.warn("修改密码失败，用户ID {} 不存在", userId);
            throw new BusinessException(404, "用户不存在");
        }

        if (!passwordUtil.matches(userPasswordDTO.getCurrentPassword(), existingUser.getPassword())) {
            log.warn("修改密码失败，用户ID {} 当前密码错误", userId);
            throw new BusinessException(400, "当前密码错误");
        }

        if (!userPasswordDTO.getNewPassword().equals(userPasswordDTO.getConfirmPassword())) {
            throw new BusinessException(400, "两次输入的新密码不一致");
        }

        if (passwordUtil.matches(userPasswordDTO.getNewPassword(), existingUser.getPassword())) {
            throw new BusinessException(400, "新密码不能与当前密码相同");
        }

        User updateUser = new User();
        updateUser.setId(userId);
        updateUser.setPassword(passwordUtil.encodePassword(userPasswordDTO.getNewPassword()));

        int updateCount = userMapper.updateById(updateUser);
        if (updateCount == 0) {
            throw new BusinessException(500, "修改密码失败");
        }

        log.info("用户密码修改成功，用户ID: {}", userId);
    }
}
